package org.anderground.editor.gui.view.android;

import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JPanel;

import org.anderground.core.Logger;
import org.anderground.core.drawer.Calculator;
import org.anderground.core.drawer.MetroDrawer;
import org.anderground.core.graphics.Canvas;
import org.anderground.core.graphics.Point;
import org.anderground.core.graphics.PointF;
import org.anderground.core.util.Coord;
import org.anderground.core.util.Coordinated;
import org.anderground.editor.model.EditorModel;
import org.anderground.internal.graphics.impl.AwtCanvas;
import org.anderground.modules.drawer.dynamic.DynamicDrawer;

@SuppressWarnings("serial")
public class AndroidDrawerPanel extends JPanel {

	private float scale = 10f;
	private int xTransform = 0, yTransform = 0;
	private MetroDrawer drawer;

	public AndroidDrawerPanel() {
		try {
			if (DrawersRegistry.getEntries().size() > 0) {
				drawer = DrawersRegistry.getEntries().get(0).getDrawerClass()
						.newInstance();
			} else {
				drawer = DynamicDrawer.class.newInstance();
			}
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public Class<? extends MetroDrawer> getDrawerClass() {
		if (drawer == null) {
			return null;
		}
		return drawer.getClass();
	}

	public void setDrawerClass(Class<? extends MetroDrawer> drawerClass) {
		try {
			this.drawer = drawerClass.newInstance();
			drawer.prepare(EditorModel.getInstance().getData(),
					Calculator.Mode.POSITION);
			this.repaint();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		if (drawer == null || !drawer.isReady()) {
			Logger.w((drawer == null) ? "drawer is not assignet"
					: "drawer is not ready");
			return;
		}
		Canvas canvas = AwtCanvas.wrap((Graphics2D) g);
		((Graphics2D) g).translate(xTransform, yTransform);
		drawer.applyCalculator(calculator);
		drawer.draw(canvas);
	}

	public void shift(int dx, int dy) {
		xTransform += dx;
		yTransform += dy;
	}

	public void reset() {
		xTransform = 0;
		yTransform = 0;
	}

	public void setScale(float scale) {
		this.scale = scale;
	}

	public float getScale() {
		return scale;
	}

	public void updateModel() {
		if (drawer != null)
			drawer.prepare(EditorModel.getInstance().getData(),
					Calculator.Mode.POSITION);
	}

	public void setCenter(int x, int y) {
		xTransform = x;
		yTransform = y;

	}

	public Point getCenter() {
		return new Point(xTransform, yTransform);

	}

	private EditorCalc calculator = new EditorCalc();

	private class EditorCalc implements Calculator {

		private float offsetX = 0, offsetY = 0;

		@Override
		public Mode getMode() {
			return Mode.POSITION;
		}

		@Override
		public void convert(Coord coord, PointF pointF) {
			pointF.x = (coord.getX() + offsetX) * scale;
			pointF.y = (coord.getY() + offsetY) * scale;
		}

		@Override
		public void convert(Coord coord, Point point) {
			point.x = (int) ((coord.getX() + offsetX) * scale);
			point.y = (int) ((coord.getY() + offsetY) * scale);
		}

		@Override
		public void convert(Coordinated coordinated, PointF pointF) {
			convert(coordinated.getPosition(), pointF);
		}

		@Override
		public void convert(Coordinated coordinated, Point point) {
			convert(coordinated.getPosition(), point);
		}

		@Override
		public void convert(PointF coordF, PointF pointF) {
			pointF.x = (coordF.x + offsetX) * scale;
			pointF.y = (coordF.y + offsetY) * scale;
		}

		@Override
		public void convert(PointF coordF, Point point) {
			point.x = (int) ((coordF.x + offsetX) * scale);
			point.y = (int) ((coordF.x + offsetX) * scale);
		}

		@Override
		public void revert(Point point, PointF coordF) {
			coordF.x = (point.x) / scale - offsetX;
			coordF.y = (point.y) / scale - offsetY;
		}

		@Override
		public void revert(PointF pointF, PointF coordF) {
			coordF.x = (pointF.x) / scale - offsetX;
			coordF.y = (pointF.y) / scale - offsetY;
		}

		@Override
		public Coord getCoord(Coordinated coordinated) {
			return coordinated.getPosition();
		}

	};

}
